if lib and not lib.GetInstrument then


function lib:IsInstrument(instrument)
	if type(instrument) == "table"
		and instrument.code
		and instrument.class_code
		and instrument.isin_code
		and instrument.regnumber
	then
		return instrument
	end
end


function lib:bool2side(side)
	if side then
		return "LONG"
	end
	
	return "SHORT"
end


function lib:GetClass(sec_code)
	local instrument = lib:GetInstrument(sec_code)
	
	if instrument then
		return instrument.class_code, instrument.sec_code
	end
end


function lib:NormalizePrice(price, instrument, side)
	local done
	
	if price and instrument then
		price = tonumber(price)
		local step = instrument.min_price_step
		
		if price < 0 then
			step = -step
		end
		
		if price % step ~= 0 then
			if side == nil then		-- round price
				price = price + step / 2
			elseif side then		-- ceiling price
				price = price + step
			--else					-- floor price
			end
			
			price = price - price % step
			
			if instrument.min_price_step >= 1 then
				price = int(price)
			end
		end
		
		done = true
	end

	return price, done
end


function lib:GetInstrument(name)
	if not self.securities then self.securities = {} end
	
	if self.securities_count ~= getNumberOf("securities") or self.securities_date ~= self:FormatDate() then
		self.securities_count = getNumberOf("securities")
		self.securities_date = self:FormatDate()
		self.instruments = {}
		local count
		self.securities, count = self:GetSecuritiesTable()
		--message("Loaded securities " .. count .. " / " .. self.securities_count)
	end
	
	if not self.instruments then self.instruments = {} end
		
	if type(name) == "table" then
	
		local instrument = self:GetInstrument(name.code)
			or self:GetInstrument(name.sec_code)
			or self:GetInstrument(name.SECCODE)
			or self:GetInstrument(name.short_name)
			or self:GetInstrument(name[1])
			
		if not instrument then
			for _, v in pairs(name) do
				instrument = self:GetInstrument(v)
			end
		end
		
		return instrument
		
	elseif type(name) == "string" then
	
		if #name <= 0 then return end
		
		if string.match(name, "^VIEW0[12]$") then	-- Chart tag
			name = lib:GetChartInstrumentName(name)
			if not name then return end
		end
		
		name = string.upper(name)
		
		if self.instruments[name] then
			return self:clone(self.instruments[name])
		end
		
		local data = self.securities[name]
		
		if not data then
			if string.match(name, "^%a%a[12]!$") then
				local futs = {}

				for code, dt in pairs(self.securities) do
					if dt.class_code == "SPBFUT" then
						if string.sub(code, 1, -3) == string.sub(name, 1, -3) then
							if not futs[1] or futs[1].mat_date > dt.mat_date then
								futs[2] = futs[1]
								futs[1] = dt
							elseif not futs[2] or futs[2].mat_date > dt.mat_date then
								futs[2] = dt
							end
						end
					end
				end
				data = futs[int(string.sub(name, -2, -2))]
			else
				for _, dt in pairs(self.securities) do
					if string.upper(dt.short_name) == name
					then
						data = dt
						break
					end
				end
			end
		end
		
		if data then
			self.instruments[name] = data
			
			return self:clone(data)
		end
	end
end


function lib:GetOptionType(sec_code)
	local instrument = sec_code
	if type(sec_code) ~= "table" then
		instrument = self:GetInstrument(sec_code)
	end
	if instrument then
		local m = string.match(instrument.code, "^%a%a%d%d%d%d%a(%a)%d$")
		if m then
			if string.match(m, "^[A-L]$") then
				return "call"
			elseif string.match(m, "^[M-X]$") then
				return "put"
			end
		end
	end
end


function lib:GetOption(base_code, is_call, strike)
	if is_call ~= nil and strike > 0 then
		local base_instrument = base_code
		if type(base_code) ~= "table" then
			base_instrument = self:GetInstrument(base_code)
		end
		if base_instrument then
			local name = string.upper(base_instrument.code)
			local dt = int(os.date("%Y%m%d", os.time(self:getTradeDate()) + 14*24*60*60))
			local opts = {}
			local t

			for _, data in pairs(self.securities) do
				if data.class_code == "SPBOPT" and data.mat_date >= dt then
					if string.upper(tostring(data.base_active_seccode)) == name then
						t = self:GetOptionType(data.code)
						if (is_call and t == "call" or not is_call and t == "put")
							and (is_call and strike < data.option_strike or not is_call and strike > data.option_strike)
						then
							table.insert(opts, data)
						end
					end
				end
			end
			if #opts > 0 then
				if is_call then
					table.sort(opts, function(a,b) return
						a.mat_date < b.mat_date
						or
						a.mat_date == b.mat_date and a.option_strike < b.option_strike
					end)
				else
					table.sort(opts, function(a,b) return
						a.mat_date < b.mat_date
						or
						a.mat_date == b.mat_date and a.option_strike > b.option_strike
					end)
				end
				return opts[1]
			end
		end
	end
end


function lib:GetInstrumentPosition(instrument)
	local positions = {}
	
	for k, pos in pairs(self:GetTable("depo_limits", "sec_code")) do
		if pos.limit_kind > 2 and int(pos.currentbal) ~= 0
			and (not instrument
				or (instrument.code or instrument) == k
			)
		then
				if not positions[k] then
					table.insert(positions, k)
					positions[k] = 0
				end
				
				positions[k] = positions[k] + int(pos.currentbal)
		end
	end
	
	for k, pos in pairs(self:GetTable("futures_client_holding", "sec_code")) do
		if int(pos.totalnet) ~= 0
			and (not instrument
				or (instrument.code or instrument) == k
			)
		then
				if not positions[k] then
					table.insert(positions, k)
					positions[k] = 0
				end
				
				positions[k] = positions[k] + int(pos.totalnet)
		end
	end
	
	if not instrument then return positions end
	return positions[instrument.code or instrument] or 0, positions
end


end -- of file
